#include "SpeakManager.h"
#include "common.h"

void ByteToHexStr(const unsigned char* source, char* dest, int sourceLen)  
{  
	short i;  
	unsigned char highByte, lowByte;  

	for (i = 0; i < sourceLen; i++)  
	{  
		highByte = source[i] >> 4;  
		lowByte = source[i] & 0x0f ;  

		highByte += 0x30;  

		if (highByte > 0x39)  
			dest[i * 2] = highByte + 0x07;  
		else  
			dest[i * 2] = highByte;  

		lowByte += 0x30;  
		if (lowByte > 0x39)  
			dest[i * 2 + 1] = lowByte + 0x07;  
		else  
			dest[i * 2 + 1] = lowByte;  
	}  
	return ;  
}

CSpeakManager::CSpeakManager(IOSpeakRecvNotify *pNotify)
: m_bExit(false)
, m_bOpenStatus(false)
, m_pRecvData(NULL)
, m_nRecvDataLen(1024)
, m_nCurrentRecvLen(0)
, m_pNotify(pNotify)
, m_bFrist(true)
{
	m_pRecvData = new char[m_nRecvDataLen];
	memset(m_pRecvData, 0x00, m_nRecvDataLen);
}

CSpeakManager::~CSpeakManager(void)
{
	Stop();

	if (m_pRecvData)
	{
		delete [] m_pRecvData;
		m_pRecvData = NULL;
	}
}

bool CSpeakManager::Start(int nComId)
{
	m_bExit = false;

	m_nComId = nComId;

	m_nCurrentRecvLen = 0;

	if (OpenCom(m_nComId))
	{
		return StartThread();
	}
	
	return false;
}

void CSpeakManager::Stop(void)
{
	if (!m_bExit)
	{
		m_bExit = true;	

		WaitForStop();

		CloseCom();
	}	
}

bool CSpeakManager::GetSpeakStatus(void)
{
	BYTE buf[] = {0x5A, 0xA5, 0x06, 0x83, 0x00,0x60, 0x01, 0x00, 0x60};

	if (SendDataToSpeak((const char *)buf, sizeof(buf)) == sizeof(buf))
		return true;

	return false;
}

bool CSpeakManager::GetSpeakIsOK(void)
{
	BYTE buf[] = {0x5A, 0xA5, 0x06, 0x83, 0x00,0x64, 0x01, 0x00, 0x64};

	if (SendDataToSpeak((const char *)buf, sizeof(buf)) == sizeof(buf))
		return true;

	return false;
}

bool CSpeakManager::SetSpeakID(int nSpeakId)
{
	BYTE szBuf[16] = {0};
	szBuf[0] = 0x5A;
	szBuf[1] = 0xA5;

	szBuf[2] = 0x06;
	szBuf[3] = 0x83;

	szBuf[4] = 0x00;
	szBuf[5] = 0x62;

	szBuf[6] = 0x01;
	szBuf[7] = nSpeakId >> 8 & 0xFF;
	szBuf[8] = nSpeakId & 0xFF;

	if (SendDataToSpeak((const char *)szBuf, sizeof(szBuf)) == sizeof(szBuf))
		return true;

	return false;
}

bool CSpeakManager::OpenSpeak(void)
{
	BYTE buf[] = {0x5A, 0xA5, 0x06, 0x83, 0x00,0x0B, 0x01, 0x00, 0x0B};

	if (SendDataToSpeak((const char *)buf, sizeof(buf)) == sizeof(buf))
		return true;

	return false;
}

bool CSpeakManager::GetSpeakId(void)
{
	BYTE buf[] = {0x5A, 0xA5, 0x06, 0x83, 0x00,0x62, 0x01, 0x00, 0x00};

	if (SendDataToSpeak((const char *)buf, sizeof(buf)) == sizeof(buf))
		return true;

	return false;
}

bool CSpeakManager::IsConnect(void)
{
	return m_bOpenStatus;
}

int CSpeakManager::SendDataToSpeak(const char *pData, int nDataLen)
{
	return m_cCom.Write((char *)pData, nDataLen);
}

void CSpeakManager::ThreadProcMain(void)
{
	while (!m_bExit)
	{
		if (m_bOpenStatus)
		{
			if (m_nCurrentRecvLen >= m_nRecvDataLen)
			{
				int nNewLen = m_nRecvDataLen * 2;

				char *pTmp = new char[nNewLen];
				memset(pTmp, 0x00, nNewLen);

				memcpy(pTmp, m_pRecvData, m_nCurrentRecvLen);
				m_nRecvDataLen = nNewLen;

				delete [] m_pRecvData;
				m_pRecvData = pTmp;
			}

			int nRet = ReadDataFromSpeak(m_pRecvData + m_nCurrentRecvLen, m_nRecvDataLen - m_nCurrentRecvLen);
			if (nRet > 0)
			{
				m_nCurrentRecvLen += nRet;

				/*char szOutMsg[1024] = {0};
				ByteToHexStr((const unsigned char *)m_pRecvData, szOutMsg, m_nCurrentRecvLen);
				OutputDebugString(szOutMsg);*/
			}

			CheckRecvData();
		}		

		my_sleep(2);
	}
}

bool CSpeakManager::OpenCom(int nComId)
{
	m_nComId = nComId;

	if (m_cCom.OpenCOM(nComId, 115200))
	{
		m_bOpenStatus = true;
		return m_bOpenStatus;
	}
	else
	{
		m_bOpenStatus = false;
		return m_bOpenStatus;
	}
}

void CSpeakManager::CloseCom(void)
{
	if (m_bOpenStatus)
	{
		m_cCom.Close();
		m_bOpenStatus = false;
	}
}

int CSpeakManager::ReadDataFromSpeak(char *pBuff, int nBuffLen)
{
	return m_cCom.Read(pBuff, nBuffLen);
}

void CSpeakManager::CheckRecvData(void)
{
	if(m_nCurrentRecvLen > 5)
	{
		if (((BYTE)m_pRecvData[0] == 0x5A) 
			&& ((BYTE)m_pRecvData[1] == 0xA5))
		{
			int nPacketLen = (BYTE)m_pRecvData[2] + 3;
			if (m_nCurrentRecvLen >= nPacketLen)
			{
				m_pNotify->OnRecvDataNotify(m_pRecvData, nPacketLen);

				memcpy(m_pRecvData, m_pRecvData + nPacketLen, m_nRecvDataLen - nPacketLen);
				m_nCurrentRecvLen -=  nPacketLen;
			}

			if (nPacketLen > 100)
				m_nCurrentRecvLen = 0;
		}
		else
		{
			char *pBuf = m_pRecvData;
			int nPos = 0;

			while (m_nCurrentRecvLen > 0)
			{
				if ((BYTE)(*pBuf) == 0x5A &&
					(BYTE)(*(pBuf+1)) == 0xA5)
				{
					memcpy(m_pRecvData, m_pRecvData + nPos, m_nRecvDataLen - nPos);
					return;					
				}
				else
				{
					pBuf++;
					nPos++;		
					m_nCurrentRecvLen--;
				}
			}
		}
	}
}
